package org.umss.fixturebuilder.builder;

import java.util.Collections;
import java.util.List;
import java.util.Random;
import org.umss.fixturebuilder.builder.model.Game;
import org.umss.fixturebuilder.builder.model.Phase;
import org.umss.fixturebuilder.builder.model.Round;
import org.umss.fixturebuilder.builder.model.Team;
import org.umss.fixturebuilder.model.appengine.PhaseType;

/**
 *
 * @author Daniela Meneses
 */
public class DirectEliminationPhaseBuilder implements PhaseBuilder {

    public static final String ODD_TEAMS_NOT_VALID = "This phase doesn't have support for odd number of teams";

    public Phase generatePhase(List<Team> teams) throws PhaseBuilderException {
        int teamsSize = teams.size();
        int roundCount = isValidTeamNumberForDE(teamsSize);
        if (roundCount == -1) {
            throw new PhaseBuilderException(ODD_TEAMS_NOT_VALID);
        }

        long seed = System.nanoTime();
        Collections.shuffle(teams, new Random(seed));
        Phase result = new Phase(PhaseType.DIRECT_ELIMINATION);
        for (int index = 0; index < roundCount; index++) {
            boolean fake = index != 0;
            teamsSize = fake ? teamsSize / 2 : teamsSize;
            result.addRound(buildRound(teams, teamsSize, fake));
        }

        return result;
    }

    public int isValidTeamNumberForDE(int size) {
        int res;

        if (size == 2) {
            res = 1;
        } else {
            if (size > 2 && size % 2 == 0) {
                int parcial = isValidTeamNumberForDE(size / 2);
                res = parcial != -1 ? 1 + parcial : parcial;
            } else {
                res = -1;
            }
        }

        return res;
    }

    public Round buildRound(List<Team> teams, int teamsSize, boolean fake) {
        Round round = new Round();
        Game game;
        for (int index = 0; index < teamsSize; index+=2) {
            
            if(fake) {
                game = new Game();
            } else {
                
                game = new Game(teams.get(index), teams.get(index+1));
            }
            round.addGame(game);
        }
        
        return round;
    }
}
